package per.edward.wechatautomationutil;

import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Parcelable;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ListView;

import org.greenrobot.eventbus.EventBus;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import per.edward.wechatautomationutil.utils.Constant;
import per.edward.wechatautomationutil.utils.Logger;

import static per.edward.wechatautomationutil.utils.Constant.WINDOW_LAUNCHER;
import static per.edward.wechatautomationutil.utils.Constant.WINDOW_LUCKYMONEY_DETAIL;
import static per.edward.wechatautomationutil.utils.Constant.WINDOW_LUCKYMONEY_RECEIVEUI;
import static per.edward.wechatautomationutil.utils.Constant.WINDOW_OTHER;

/**
 * Created by Edward on 2018-01-30.
 */
// @TargetApi(18)
public class AccessibilitySampleService extends AccessibilityService {
    private final int TEMP = 2000;
    private static Logger logger;
    private static final String TAG = "WeChatAutomationUtil";
    private static int mCurrentWindow;

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        flag = false;
        if (Logger.logService.getState() == Thread.State.NEW) {
            Logger.logService.start();
        }
        logger = Logger.getInstance(getBaseContext());

        Notification.Builder localBuilder = new Notification.Builder(this);
        localBuilder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
        localBuilder.setAutoCancel(false);
        localBuilder.setSmallIcon(R.drawable.ic_stat_name);
        localBuilder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
        localBuilder.setTicker("运行中...");
        localBuilder.setContentTitle(getResources().getString(R.string.app_name));
        localBuilder.setContentText("准备抢红包");
        startForeground(2019, localBuilder.build());
    }

    private AccessibilityNodeInfo accessibilityNodeInfo;

    /**
     * 是否已经发送过朋友圈，true已经发送，false还未发送
     */
    public static boolean flag = false;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        String eventTypeDesc = getEventType(eventType);
        logger.e(eventTypeDesc + "             " + event.getClassName());
        accessibilityNodeInfo = getRootInActiveWindow();
        switch (eventType) {
            case AccessibilityEvent.TYPE_VIEW_SCROLLED:
                if (event.getClassName().equals("android.widget.ListView")) {
                    openPacket(event.getSource());
                }
                break;
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
                Parcelable data = event.getParcelableData();
                if (data instanceof Notification) {

                    Notification notification = (Notification) data;
                    String pkgName = (String) event.getPackageName();

                    Object fn = notification.extras.get(Notification.EXTRA_TITLE);
                    Object txt = notification.extras.get(Notification.EXTRA_TEXT);
                    if (fn == null || txt == null) {
                        return;
                    }
                    String fromName = fn.toString();
                    String text = txt.toString();
                    logger.i(pkgName + "   " + fromName + "   " + text);
                    if (text.lastIndexOf(Constant.WX_ENVELOPE_KEYWORD) >= 0) {
                        try {
                            PendingIntent pendingIntent = notification.contentIntent;
                            pendingIntent.send();
                        } catch(PendingIntent.CanceledException e) {
                            e.printStackTrace();
                        }
                    }
                }
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                String className = event.getClassName().toString();
                switch (className) {
                    case "com.tencent.mm.ui.LauncherUI":
                        mCurrentWindow = WINDOW_LAUNCHER;   //开始抢红包
                        logger.i("准备抢红包...");
                        //getPacket();
                        break;
                    case "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI":
                        mCurrentWindow = WINDOW_LUCKYMONEY_RECEIVEUI;  //开始打开红包
                        logger.i("打开红包");
                        //openPacket();
                        EventBus.getDefault().post("wakeup");
                        break;
                    case "com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI":
                        mCurrentWindow = WINDOW_LUCKYMONEY_DETAIL;    //返回以方便下次收红包
                        logger.i("返回");
                        back2Home(0);
                    default:
                        mCurrentWindow = WINDOW_OTHER;
                }
                break;
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                if(mCurrentWindow != WINDOW_LAUNCHER) { //不在聊天界面或聊天列表，不处理
                    return;
                }
                break;
            default:
                break;
        }
    }

    private static String getEventType(int typeValue) {
        Field[] fields = AccessibilityEvent.class.getDeclaredFields();
        for (Field field : fields) {
            int modifies = field.getModifiers();
            try {
                String fieldType = field.getType().getCanonicalName();
                if (Modifier.isStatic(modifies) && Modifier.isPublic(modifies) && Modifier.isFinal(modifies) && fieldType.equalsIgnoreCase("int") && field.getInt(null) == typeValue) {
                    return field.getName();
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private void openPacket(AccessibilityNodeInfo chatsNodeInfo) {
        if (chatsNodeInfo.getChildCount() > 0) {
            logger.i("found " + chatsNodeInfo.getChildCount() + " chat info");
            for (int i = 0; i < chatsNodeInfo.getChildCount(); i++) {
                AccessibilityNodeInfo chatNodeInfo = chatsNodeInfo.getChild(0);
                logger.i("chat info node is " + (chatNodeInfo.isClickable() ? " clickable" : " unclickable") + chatNodeInfo.getClassName() + ", has " + chatNodeInfo.getChildCount() + " children");
                if (chatNodeInfo.getClassName().equals("android.widget.RelativeLayout") && chatNodeInfo.getChildCount() > 0) {
                    for(int j = 0; j < chatNodeInfo.getChildCount(); j++) {
                        AccessibilityNodeInfo containerChildNodeInfo = chatNodeInfo.getChild(j);
                        String className = containerChildNodeInfo.getClassName().toString();
                        logger.d(className);
                        if (className.equals("android.widget.LinearLayout")) {
                            logger.i((j+1) + "th child is " + className + ", has "+containerChildNodeInfo.getChildCount()+" children");
                            AccessibilityNodeInfo moneyNodeInfo = containerChildNodeInfo.getChild(1);
                            List<AccessibilityNodeInfo> moneyTitleChildrenInfo = moneyNodeInfo.findAccessibilityNodeInfosByText(Constant.WX_ENVELOPE_TITLE_KEYWORD);
                            List<AccessibilityNodeInfo> moneyDrawedBySelfTextChildrenInfo = moneyNodeInfo.findAccessibilityNodeInfosByText(Constant.WX_ENVELOPE_TEXT_DRAWED_BY_SELF);
                            List<AccessibilityNodeInfo> moneyDrawedByOthersTextChildrenInfo = moneyNodeInfo.findAccessibilityNodeInfosByText(Constant.WX_ENVELOPE_TEXT_DRAWED_BY_OTHERS);
                            List<AccessibilityNodeInfo> moneyContentChildrenInfo = moneyNodeInfo.findAccessibilityNodeInfosByText(Constant.WX_ENVELOPE_CONTENT_KEYWORD);
                            logger.i("found " + moneyTitleChildrenInfo.size() + " money-like text");
                            if (moneyDrawedBySelfTextChildrenInfo.size() == 0 && moneyDrawedByOthersTextChildrenInfo.size() == 0 && moneyTitleChildrenInfo.size() > 0) {
                                chatNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                            }

                        }
                    }
                }
            }
        } else {
            logger.e("no chat info found");
        }

    }

    private AccessibilityNodeInfo getChild(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo.getChildCount() > 0) {
            AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(0);
            return childNodeInfo.getClassName().equals("android.widget.ListView") ? childNodeInfo : getChild(childNodeInfo);
        }
        return null;
    }

    /**
     * 回到系统桌面
     */
    private void back2Home(int time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Intent home = new Intent(Intent.ACTION_MAIN);
        home.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        home.addCategory(Intent.CATEGORY_HOME);
        startActivity(home);
    }

    @Override
    public void onInterrupt() {

    }


    /**
     * Called by the system to notify a Service that it is no longer used and is being removed.  The
     * service should clean up any resources it holds (threads, registered
     * receivers, etc) at this point.  Upon return, there will be no more calls
     * in to this Service object and it is effectively dead.  Do not call this method directly.
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        logger.e("服务被杀死!");
    }
}
